package com.alphacsp.theedge2012.data.database;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import com.alphacsp.theedge2012.data.entities.Event;
import com.alphacsp.theedge2012.data.entities.Session;
import com.alphacsp.theedge2012.data.entities.Speaker;
import com.alphacsp.theedge2012.network.WebserviceClient;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Gilad
 * Date: 30/10/10
 * Time: 00:49
 */
public class DataAccessor {

    private final DatabaseHelper databaseHelper;
    private final Context context;
    private final ConnectivityManager connectivityManager;

    private volatile static DataAccessor singleton;

    private DataAccessor(Context context) {
        this.context = context;
        this.databaseHelper = new DatabaseHelper(context);
        this.connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    public static DataAccessor getSingleton(Context context) {
        if (singleton == null) {
            synchronized (DataAccessor.class) {
                if (singleton == null) {
                    singleton = new DataAccessor(context);
                }
            }
        }
        return singleton;
    }

    public List<Speaker> getAllSpeakers() {
        return databaseHelper.getAllSpeakers();
    }

    public boolean syncAllSpeakers() {
        if (shouldUpdate(ServicesEnum.SPEAKERS)) {
            final List<Speaker> speakerList = WebserviceClient.fetchSpeakers();
            databaseHelper.storeSpeakers(speakerList, new Date());
            return true;
        }
        return false;
    }

    public List<Session> getAllSessions() {
        return databaseHelper.getAllSessions();
    }

    public boolean syncAllSessions() {
        if (shouldUpdate(ServicesEnum.SESSIONS)) {
            final List<Session> sessionList = WebserviceClient.fetchSessions();
            databaseHelper.storeSessions(sessionList, new Date());
            return true;
        }
        return false;
    }

    public List<Event> getAllEvents() {
        return databaseHelper.getAllEvents();
    }

    public boolean syncAllEvents() {
        if (shouldUpdate(ServicesEnum.SCHEDULE)) {
            final List<Event> eventList = WebserviceClient.fetchSchedule();
            databaseHelper.storeSchedule(eventList, new Date());
            return true;
        }
        return false;
    }

    public Session getSession(String sessionName) {
        return databaseHelper.getSessionByName(sessionName);
    }

    public List<Session> getSessionsBySpeaker(String speakerName) {
        return databaseHelper.getSessionsBySpeaker(speakerName);
    }

    public List<Session> getParallelSessions(String sessionName) {
        return databaseHelper.getParallelSessions(sessionName);
    }

    public Bitmap fetchImage(String imageUri) {
        Bitmap bitmap = null;
        final String imageFilePath = databaseHelper.getImageFilePath(imageUri);
        if (imageFilePath == null) {
            bitmap = fetchAndStoreImage(imageUri);
        } else {
            final File fileStreamPath = context.getFileStreamPath(imageFilePath);
            bitmap = BitmapFactory.decodeFile(fileStreamPath.getAbsolutePath());
            //maybe something went wrong, we'll try again
            if (bitmap == null) {
                bitmap = fetchAndStoreImage(imageUri);
            }
        }
        return bitmap;
    }

    private Bitmap fetchAndStoreImage(String imageUri) {
        Bitmap bitmap = null;
        if (isInternetConnectionActive()) {
            final String fileName = String.valueOf(System.nanoTime());
            bitmap = WebserviceClient.fetchImage(imageUri);
            try {
                FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
                fos.flush();
                fos.close();
                databaseHelper.storeFileLocation(imageUri, fileName);
            } catch (IOException e) {
                Log.e(this.getClass().getSimpleName(), "Error executing request", e);
            }
        }
        return bitmap;
    }

    public List<Session> searchSessions(String query) {
        return databaseHelper.searchSessions(query);
    }

    public List<Speaker> searchSpeakers(String query) {
        return databaseHelper.searchSpeakers(query);
    }

    public void closeDatabase() {
        databaseHelper.closeDatabase();
    }

    public void forceUpdate() {
        if (isInternetConnectionActive()) {
            databaseHelper.storeSpeakers(WebserviceClient.fetchSpeakers(), new Date());
            databaseHelper.storeSessions(WebserviceClient.fetchSessions(), new Date());
            databaseHelper.storeSchedule(WebserviceClient.fetchSchedule(), new Date());
        }
    }


    public boolean isInternetConnectionActive() {
        final NetworkInfo wifiInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        final NetworkInfo mobileInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        final NetworkInfo wimaxInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIMAX);
        return wifiInfo != null && wifiInfo.isConnected() || mobileInfo != null && mobileInfo.isConnected() || wimaxInfo != null && wimaxInfo.isConnected();
    }

    private boolean shouldUpdate(ServicesEnum servicesEnum) {
        if (!isInternetConnectionActive()) {
            return false;
        }
        final Date lastModifiedDate = WebserviceClient.getLastModifiedDate(servicesEnum.getServiceUrl());
        final Date lastModifiedDBDate = databaseHelper.getLastModifiedDate(servicesEnum.getServiceTable());
        return lastModifiedDBDate == null || lastModifiedDate.after(lastModifiedDBDate);
    }


}
